<template>
  <n-space vertical>
    <n-space>
      <SearchForm @handleSearch="handlePageQuery" :searchModel="pageQueryParam.param">
        <n-form-item label="应用名称:" path="applicationName">
          <n-input round clearable placeholder="请输入应用名称" v-model:value="pageQueryParam.param.applicationName"/>
        </n-form-item>
        <n-form-item label="任务类名:" path="jobClassName">
          <n-input round clearable placeholder="请输入任务类名" v-model:value="pageQueryParam.param.jobClassName"/>
        </n-form-item>
        <n-form-item label="任务名称:" path="jobName">
          <n-input round clearable placeholder="请输入任务名称" v-model:value="pageQueryParam.param.jobName"/>
        </n-form-item>
      </SearchForm>
    </n-space>
    <n-space>
      <AddButton @handleAdd="showModal = true"/>
    </n-space>
    <n-space>
      <PageTable @handlePageQuery="handlePageQuery" :columns="columns" :loading="loading" :pageResult="pageResult"/>
    </n-space>
  </n-space>

  <UpdateModal :showModal="showModal" :paramModel="addMetaDataParam" :rules="rules" @handleSubmit="handleUpdate" @clearParam="clearAddParam">
    <n-form-item label="应用名称" path="applicationName">
      <n-input v-model:value="addMetaDataParam.applicationName" size="large" placeholder="请输入应用名称" clearable/>
    </n-form-item>
    <n-form-item label="任务类名" path="jobClassName">
      <n-input v-model:value="addMetaDataParam.jobClassName" size="large" placeholder="请输入任务类名" clearable/>
    </n-form-item>
    <n-form-item label="任务名称" path="jobName">
      <n-input v-model:value="addMetaDataParam.jobName" size="large" placeholder="请输入任务名称" clearable/>
    </n-form-item>
    <n-form-item label="失败重试次数" path="jobRetryTimes">
      <n-input-number :disabled="addMetaDataParam.jobCycle === 6" v-model:value="addMetaDataParam.jobRetryTimes" size="large"
                      placeholder="请输入失败重试次数" clearable/>
    </n-form-item>
    <n-form-item label="失败重试间隔(分钟)" path="jobRetryInterval">
      <n-input-number :disabled="addMetaDataParam.jobCycle === 6" v-model:value="addMetaDataParam.jobRetryInterval" size="large"
                      placeholder="请输入失败重试间隔" clearable/>
    </n-form-item>
    <n-form-item label="执行周期" path="jobCycle">
      <n-select v-model:value="addMetaDataParam.jobCycle" placeholder="请选择执行周期" :options="jobCycleOptions"
                @update:value="checkRetryEnable"/>
    </n-form-item>
  </UpdateModal>

  <UpdateModal :showModal="showAddScheduleModal" :paramModel="addScheduleParam" :rules="addScheduleRules" @handleSubmit="handleUpdateSchedule"
               @clearParam="clearAddScheduleParam">
    <n-grid :cols="24" :x-gap="24">
      <n-form-item-gi :span="24" label="调度名称" path="scheduleName">
        <n-input v-model:value="addScheduleParam.scheduleName" size="large" placeholder="请输入调度名称" clearable/>
      </n-form-item-gi>
      <n-form-item-gi :span="24" label="执行参数" path="scheduleParam">
        <n-input v-model:value="addScheduleParam.scheduleParam" size="large" type="textarea" placeholder="请输入执行参数" clearable/>
      </n-form-item-gi>
      <n-form-item-gi :span="24" label="是否开启" path="scheduleEnable">
        <n-switch v-model:value="addScheduleParam.scheduleEnable">
          <template #checked>
            是
          </template>
          <template #unchecked>
            否
          </template>
        </n-switch>
      </n-form-item-gi>
      <n-form-item-gi :span="6" label="执行时间">
        <div v-show="currJobCycle > 0">
          每{{ currJobCycleStr }}
        </div>
      </n-form-item-gi>
      <n-form-item-gi :span="6" path="cronMonth" v-if="currJobCycle === 1">
        <n-select style="width: 90px" v-model:value="addScheduleParam.cronMonth" :options="monthOptions"/>
        月
      </n-form-item-gi>
      <n-form-item-gi :span="12" path="cronDay" v-if="currJobCycle === 1 || currJobCycle === 2">
        <n-select style="width: 90px" v-model:value="addScheduleParam.cronDay" :options="dayOptions"/>
        日
      </n-form-item-gi>
      <n-form-item-gi :span="18" path="cronDay" v-if="currJobCycle === 3">
        <n-select style="width: 90px" v-model:value="addScheduleParam.cronDay" :options="weekOptions"/>
      </n-form-item-gi>
      <n-form-item-gi :offset="currJobCycle === 4 ? 0 : 6" :span="6" path="cronHour" v-if="currJobCycle === 1 ||
      currJobCycle === 2 || currJobCycle === 3 || currJobCycle === 4">
        <n-select style="width: 90px" v-model:value="addScheduleParam.cronHour" :options="hourOptions"/>
        时
      </n-form-item-gi>
      <n-form-item-gi :span="6" path="cronMinute" v-if="currJobCycle === 1 || currJobCycle === 2 ||
      currJobCycle === 3 || currJobCycle === 4 || currJobCycle === 5">
        <n-select style="width: 90px" v-model:value="addScheduleParam.cronMinute" :options="minuteOptions"/>
        分
      </n-form-item-gi>
      <n-form-item-gi :span="6" path="cronSecond" v-if="currJobCycle === 1 || currJobCycle === 2 ||
      currJobCycle === 3 || currJobCycle === 4 || currJobCycle === 5 || currJobCycle === 6">
        <n-select style="width: 90px" v-model:value="addScheduleParam.cronSecond" :options="secondOptions"/>
        秒
      </n-form-item-gi>
    </n-grid>
  </UpdateModal>

</template>

<script lang="ts" setup>
import {h, reactive, onMounted, toRefs, computed} from "vue";
import MetaDataApi from "../api/MetaDataApi";
import {
  AddMetaDataParam,
  PageQueryMetaDataParam,
  JobMetaDataVO,
  basicColumns,
  rules,
  monthOptions,
  dayOptions,
  hourOptions,
  minuteOptions,
  secondOptions,
  weekOptions
} from
      "../model/MetaData";
import {PageQuery, PageResult} from "../model/Common";
import ConfirmButton from "../components/table/ConfirmButton.vue";
import UpdateButton from "../components/table/UpdateButton.vue";
import SearchForm from "../components/table/SearchForm.vue";
import AddButton from "../components/table/AddButton.vue";
import UpdateModal from "../components/table/UpdateModal.vue";
import PageTable from "../components/table/PageTable.vue";
import Schedule from "../views/Schedule.vue";
import {AddScheduleParam, JobScheduleVO, rules as scheduleRules} from "../model/Schedule";
import store from "../store";
import ScheduleApi from "../api/ScheduleApi";
import {InternalRowData, TableColumn} from "naive-ui/es/data-table/src/interface";

const appStore = store();
const jobCycleOptions = appStore.enumOptionStore.JobCycle;
const jobCycleMap = appStore.enumMapStore.JobCycle;

const data = reactive({
  pageQueryParam: new PageQuery<PageQueryMetaDataParam>(new PageQueryMetaDataParam()),
  pageResult: new PageResult<JobMetaDataVO>(),
  addMetaDataParam: new AddMetaDataParam(),
  addScheduleParam: new AddScheduleParam(),
  currJobCycle: -1,
  updateId: -1n,
  updateScheduleId: -1n,
  showModal: false,
  showAddScheduleModal: false,
  loading: false
});

const currJobCycleStr = computed(() => {
  return jobCycleMap.get(data.currJobCycle as number);
});

const addScheduleRules = computed(() => {
  if (data.currJobCycle < 0) {
    return scheduleRules;
  }
  let result = {...scheduleRules};
  const cycle = data.currJobCycle;
  if (cycle === 1) {
    result["cronMonth"] = {
      type: "number",
      required: true,
      message: "请选择月份",
      trigger: ["change"]
    };
  }
  if (cycle <= 2) {
    result["cronDay"] = {
      type: "number",
      required: true,
      message: "请选择日期",
      trigger: ["change"]
    };
  }
  if (cycle === 3) {
    result["cronDay"] = {
      type: "number",
      required: true,
      message: "请选择星期",
      trigger: ["change"]
    };
  }
  if (cycle <= 4) {
    result["cronHour"] = {
      type: "number",
      required: true,
      message: "请选择小时",
      trigger: ["change"]
    };
  }
  if (cycle <= 5) {
    result["cronMinute"] = {
      type: "number",
      required: true,
      message: "请选择分钟",
      trigger: ["change"]
    };
  }
  if (cycle <= 6) {
    result["cronSecond"] = {
      type: "number",
      required: true,
      message: "请选择秒钟",
      trigger: ["change"]
    };
  }
  return result;
});

const checkRetryEnable = (): void => {
  if (data.addMetaDataParam.jobCycle === 6) {
    data.addMetaDataParam.jobRetryTimes = 0;
    data.addMetaDataParam.jobRetryInterval = 0;
  }
}

const handleUpdate = (): void => {
  if (data.updateId === -1n) {
    MetaDataApi.addMetaData(data.addMetaDataParam).then(() => {
      handlePageQuery();
      clearAddParam();
    });
  } else {
    MetaDataApi.updateMetaData({...data.addMetaDataParam, id: data.updateId}).then(() => {
      handlePageQuery();
      clearAddParam();
    });
  }
};

const clearAddParam = (): void => {
  data.showModal = false;
  data.addMetaDataParam = {} as AddMetaDataParam;
  data.updateId = -1n;
};

const handlePageQuery = (page?: number, size?: number): void => {
  if (page) {
    data.pageQueryParam.page = page;
  }
  if (size) {
    data.pageQueryParam.size = size;
  }
  data.loading = true;
  MetaDataApi.pageList(data.pageQueryParam)
      .then(response => {
        if (response) {
          data.pageResult = response;
        }
        data.loading = false;
      });
};

const showUpdate = (rowData: JobMetaDataVO): void => {
  data.updateId = rowData.id as bigint;
  data.addMetaDataParam.jobName = rowData.jobName;
  data.addMetaDataParam.jobClassName = rowData.jobClassName;
  data.addMetaDataParam.applicationName = rowData.applicationName;
  data.addMetaDataParam.jobRetryInterval = rowData.jobRetryInterval;
  data.addMetaDataParam.jobRetryTimes = rowData.jobRetryTimes;
  data.addMetaDataParam.jobCycle = rowData.jobCycle;
  data.showModal = true;
};

const showAddSchedule = (rowData: JobMetaDataVO): void => {
  data.addScheduleParam.jobMetaDataId = rowData.id;
  data.currJobCycle = rowData.jobCycle as number;
  data.showAddScheduleModal = true;
};

const showUpdateSchedule = (rowData: JobScheduleVO): void => {
  data.updateScheduleId = rowData.id as bigint;
  data.currJobCycle = rowData.jobCycle as number;
  data.addScheduleParam.scheduleName = rowData.scheduleName;
  data.addScheduleParam.scheduleParam = rowData.scheduleParam;
  data.addScheduleParam.scheduleEnable = rowData.scheduleEnable as boolean;
  data.addScheduleParam.cronMonth = rowData.cronMonth;
  data.addScheduleParam.cronDay = rowData.cronDay;
  data.addScheduleParam.cronHour = rowData.cronHour;
  data.addScheduleParam.cronMinute = rowData.cronMinute;
  data.addScheduleParam.cronSecond = rowData.cronSecond;
  data.showAddScheduleModal = true;
}

const handleDelete = (id: bigint): void => {
  MetaDataApi.deleteMetaData(id).then(() => {
    handlePageQuery();
  });
};

const expandColumn: TableColumn<InternalRowData> = {
  type: "expand",
  expandable: (rowData: JobMetaDataVO) => rowData.hasSchedule as boolean,
  renderExpand: (rowData: JobMetaDataVO) => {
    return h(Schedule, {
      jobMetaDataId: rowData.id,
      applicationName: rowData.applicationName,
      onShowUpdateSchedule: (rowData: JobScheduleVO): void => showUpdateSchedule(rowData)
    });
  }
};

const optionsColumn: TableColumn<InternalRowData> = {
  title: "操作",
  key: "options",
  width: 340,
  render: (rowData: JobMetaDataVO) => {
    return [
      h(ConfirmButton, {onHandleEvent: () => handleDelete(rowData.id as bigint), iconType: "delete", disabled: false}),
      h(UpdateButton, {onShowUpdate: () => showUpdate(rowData)}),
      h(UpdateButton, {onShowUpdate: () => showAddSchedule(rowData), content: "添加调度配置"})
    ];
  }
};

const handleUpdateSchedule = (): void => {
  if (data.updateScheduleId === -1n) {
    ScheduleApi.addJobSchedule(data.addScheduleParam).then(() => {
      handlePageQuery();
      clearAddScheduleParam();
    });
  } else {
    ScheduleApi.updateJobSchedule({...data.addScheduleParam, id: data.updateScheduleId}).then(() => {
      handlePageQuery();
      clearAddScheduleParam();
    });
  }
};

const clearAddScheduleParam = (): void => {
  data.showAddScheduleModal = false;
  data.addScheduleParam = new AddScheduleParam();
  data.updateScheduleId = -1n;
  data.currJobCycle = -1;
}

const columns: TableColumn<InternalRowData>[] = [expandColumn, ...basicColumns, optionsColumn];
const {pageQueryParam, pageResult, addMetaDataParam, showModal, loading, showAddScheduleModal, addScheduleParam, currJobCycle} = toRefs(data);

onMounted(() => {
  handlePageQuery();
});
</script>
